#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis/hiredis.h>

// Custom string duplication function that works on all platforms
static char* duplicate_string(const char* str) {
    if (!str) return NULL;
    size_t len = strlen(str) + 1;
    char* dup = (char*)malloc(len);
    if (dup) {
        strcpy(dup, str);
    }
    return dup;
}

// Redis连接结构体
typedef struct {
    redisContext *context;
} RedisClient;

// 连接到Redis服务器
RedisClient* redis_connect(const char *hostname, int port) {
    RedisClient *client = (RedisClient*)malloc(sizeof(RedisClient));
    if (!client) {
        printf("Redis Connection error: can't allocate redis client struct\n");
        return NULL;
    }
    struct timeval timeout = {1, 500000}; // 1.5 seconds
    client->context = redisConnectWithTimeout(hostname, port, timeout);
    if (client->context == NULL || client->context->err) {
        if (client->context) {
            printf("Redis Connection error: %s\n", client->context->errstr);
            redisFree(client->context);
        } else {
            printf("Redis Connection error: can't allocate redis context\n");
        }
        free(client);
        return NULL;
    }
    return client;
}

// 断开Redis连接
void redis_disconnect(RedisClient *client) {
    if (client) {
        if (client->context) {
            redisFree(client->context);
        }
        free(client);
    }
}

// 设置字符串键值
int redis_set(RedisClient *client, const char *key, const char *value) {
    if (!client || !client->context) return -1;
    redisReply *reply = (redisReply*)redisCommand(client->context, "SET %s %s", key, value);
    if (!reply) return -1;
    int success = (reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "OK") == 0);
    freeReplyObject(reply);
    return success ? 0 : -1;
}

// 获取字符串键值
char* redis_get(RedisClient *client, const char *key) {
    if (!client || !client->context) return NULL;
    redisReply *reply = (redisReply*)redisCommand(client->context, "GET %s", key);
    char *result = NULL;
    if (reply && reply->type == REDIS_REPLY_STRING) {
        result = duplicate_string(reply->str);
    }
    if (reply) freeReplyObject(reply);
    return result;
}

// 哈希表设置字段
int redis_hset(RedisClient *client, const char *hash, const char *field, const char *value) {
    if (!client || !client->context) return -1;
    redisReply *reply = (redisReply*)redisCommand(client->context, "HSET %s %s %s", hash, field, value);
    if (!reply) return -1;
    int success = (reply->type == REDIS_REPLY_INTEGER);
    freeReplyObject(reply);
    return success ? 0 : -1;
}

// 哈希表获取字段
char* redis_hget(RedisClient *client, const char *hash, const char *field) {
    if (!client || !client->context) return NULL;
    redisReply *reply = (redisReply*)redisCommand(client->context, "HGET %s %s", hash, field);
    char *result = NULL;
    if (reply && reply->type == REDIS_REPLY_STRING) {
        result = duplicate_string(reply->str);
    }
    if (reply) freeReplyObject(reply);
    return result;
}

// 列表左侧插入
int redis_lpush(RedisClient *client, const char *list, const char *value) {
    if (!client || !client->context) return -1;
    redisReply *reply = (redisReply*)redisCommand(client->context, "LPUSH %s %s", list, value);
    if (!reply) return -1;
    int success = (reply->type == REDIS_REPLY_INTEGER);
    freeReplyObject(reply);
    return success ? 0 : -1;
}

// 列表右侧插入
int redis_rpush(RedisClient *client, const char *list, const char *value) {
    if (!client || !client->context) return -1;
    redisReply *reply = (redisReply*)redisCommand(client->context, "RPUSH %s %s", list, value);
    if (!reply) return -1;
    int success = (reply->type == REDIS_REPLY_INTEGER);
    freeReplyObject(reply);
    return success ? 0 : -1;
}

// 删除键
int redis_del(RedisClient *client, const char *key) {
    if (!client || !client->context) return -1;
    redisReply *reply = (redisReply*)redisCommand(client->context, "DEL %s", key);
    if (!reply) return -1;
    int success = (reply->type == REDIS_REPLY_INTEGER && reply->integer > 0);
    freeReplyObject(reply);
    return success ? 0 : -1;
}

// 获取键的TTL
int redis_ttl(RedisClient *client, const char *key) {
    if (!client || !client->context) return -2;
    redisReply *reply = (redisReply*)redisCommand(client->context, "TTL %s", key);
    int ttl = -2; // -2: key不存在, -1: 永不过期, >=0: 剩余秒数
    if (reply && reply->type == REDIS_REPLY_INTEGER) {
        ttl = reply->integer;
    }
    if (reply) freeReplyObject(reply);
    return ttl;
}

// 测试函数
void test_redis_connection() {
    printf("=== Testing Redis Connection ===\n");
    
    // 连接到Redis服务器
    RedisClient *client = redis_connect("127.0.0.1", 6379);
    if (!client) {
        printf("Redis 连接失败！\n");
        return;
    }
    printf("Redis 连接成功！\n");

    // 示例：设置和获取一个字符串键值
    if (redis_set(client, "test_key", "hello redis") == 0) {
        printf("✓ SET operation successful\n");
        char *value = redis_get(client, "test_key");
        if (value) {
            printf("✓ GET operation successful: %s\n", value);
            free(value);
        } else {
            printf("✗ GET operation failed\n");
        }
    } else {
        printf("✗ SET operation failed\n");
    }

    // 示例：哈希表操作
    if (redis_hset(client, "myhash", "field1", "value1") == 0) {
        printf("✓ HSET operation successful\n");
        char *hval = redis_hget(client, "myhash", "field1");
        if (hval) {
            printf("✓ HGET operation successful: %s\n", hval);
            free(hval);
        } else {
            printf("✗ HGET operation failed\n");
        }
    } else {
        printf("✗ HSET operation failed\n");
    }

    // 断开连接
    redis_disconnect(client);
    printf("=== Redis Test Completed ===\n");
}

// 主函数
int main() {
    test_redis_connection();
    return 0;
}
